/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package team11;

/**
 * 神经网络层实现类
 *
 * @author Saimi，朱婧雯
 * @see Neuron
 * @see NeuralNetwork
 */
import java.util.Random;

public class Layer {

    public Neuron[] neurons;
    public double[] outputs;

    /**
     * 层构造函数
     *
     * @param neuronCount 当前层的神经元数量，决定该层的输出维度
     * @param inputCountPerNeuron 每个神经元接收的输入数量（即前一层的神经元数量）
     * @param rand 随机数生成器，用于权重和偏置的随机初始化
     * @throws IllegalArgumentException 如果神经元数量或输入数量为负数
     *
     */
    public Layer(int neuronCount, int inputCountPerNeuron, Random rand) {
        // 参数验证
        if (neuronCount <= 0) {
            throw new IllegalArgumentException("神经元数量必须大于0");
        }
        if (inputCountPerNeuron < 0) {
            throw new IllegalArgumentException("输入数量不能为负数");
        }

        // 初始化神经元数组
        neurons = new Neuron[neuronCount];
        for (int i = 0; i < neuronCount; i++) {
            // 创建神经元，指定其连接到下一层的数量
            neurons[i] = new Neuron(inputCountPerNeuron, rand);
        }

        // 初始化输出数组
        outputs = new double[neuronCount];
    }

    /**
     * 前向传播计算
     *
     * @param inputs 输入数据数组，来自前一层的输出或原始输入
     * @return 当前层的输出数组副本（防止外部修改内部状态）
     * @throws IllegalArgumentException 如果输入数据为null或维度不匹配
     */
    public double[] forward(double[] inputs) {
        // 参数验证
        if (inputs == null) {
            throw new IllegalArgumentException("输入数据不能为null");
        }
        if (inputs.length != neurons[0].weights.length) {
            throw new IllegalArgumentException("输入数据维度与神经元权重维度不匹配");
        }

        // 并行计算所有神经元的输出
        for (int i = 0; i < neurons.length; i++) {
            outputs[i] = neurons[i].activate(inputs);
        }

        // 返回输出副本，防止外部修改内部状态
        return outputs.clone();
    }

    /**
     * 获取当前层的输出值
     *
     * @return 当前层的输出数组（注意：返回的是内部数组引用）
     * @throws IllegalStateException 如果尚未执行前向传播计算
     */
    public double[] getOutputs() {
        // 检查是否已执行前向传播
        if (outputs == null || outputs.length == 0) {
            throw new IllegalStateException("尚未执行前向传播计算，无法获取输出");
        }
        return outputs;
    }

    /**
     * 获取当前层的神经元数量
     *
     * @return 当前层的神经元数量
     */
    public int getNeuronCount() {
        return neurons.length;
    }

    /**
     * 获取指定索引的神经元
     *
     * @param index 神经元索引（从0开始）
     * @return 指定索引的神经元对象
     * @throws IndexOutOfBoundsException 如果索引超出有效范围
     */
    public Neuron getNeuron(int index) {
        if (index < 0 || index >= neurons.length) {
            throw new IndexOutOfBoundsException("神经元索引越界: " + index);
        }
        return neurons[index];
    }

    /**
     * 获取层的配置信息
     *
     * @return 层的配置信息字符串
     */
    @Override
    public String toString() {
        return String.format("Layer[neurons=%d, inputsPerNeuron=%d]",
                neurons.length,
                neurons.length > 0 ? neurons[0].weights.length : 0);
    }
}
